//////////////////////////////////////////////////////////
// Support for multiple inheritance

Function.prototype.extend = function( parentClassOrObject ){ 
	if ( parentClassOrObject.constructor == Function ) 
	{ 
		//Normal Inheritance 
		this.prototype = new parentClassOrObject;
		this.prototype.constructor = this;
		this.prototype.parent = parentClassOrObject.prototype;
	} 
	else 
	{ 
		//Pure Virtual Inheritance 
		this.prototype = parentClassOrObject;
		this.prototype.constructor = this;
		this.prototype.parent = parentClassOrObject;
	} 
	return this;
} 

var waveLib = { };

////////////////////////////////////////////////////////////
// Helper function

// <public />
// Constructs a GUID out of random numbers.
// However, a better GUID would involve IP addresses etc.
// but we do not have it.
// <param name="sep" optional="true"></param>
waveLib.createGUID = function(sep)
{    
    if ( !sep )
        sep = "-";
    var str = "";    
    for( var i = 0; i < 8; ++i )
    {
        var v = Math.floor( Math.random() * 0xFFFF );
		var vstr = v.toString(16);
		while( vstr.length < 4 )
			vstr = "0" + vstr;
        if ( i <= 1 )
            str += vstr;
        else if ( i <= 5 )
            str += sep + vstr;
        else
            str += vstr;
    }
    return str;
};

waveLib.callback = function(callback, object)
{
    return function() { callback.call(object); };
};
    
////////////////////////////////////////////////////////////
// Global variables


// The scalar clock
waveLib._clock = 1;
// ID of the current session
waveLib._session = waveLib.createGUID();
// All registered state objects
waveLib._states = { };


////////////////////////////////////////////////////////////
// GadgetState

waveLib.GadgetState = function( gadget )
{
    this.gadget = gadget;
    this.actions = {};
    // Sorted list of all actions
    this.actionList = [];
    // Actions which have been submitted but not yet acknowledged
    this.pendingActions = { };    
    this.initialized = false;
};

waveLib.GadgetState.prototype.submitAction_ = function( action )
{
    this.pendingActions[ action.getKey() ] = action;
    this.insertAction_( action );
//    $System.Console.WriteLine("Submit "+ action.getKey());
    wave.getState().submitValue( action.getKey(), action.getJSONData() );
};

waveLib.GadgetState.prototype.insertAction_ = function( action )
{
    // Keep records that this action is known
    this.actions[ action.getKey() ] = action;
    
    var index = 0;
    // Insert the action in a sorted list.
    for( var i = this.actionList.length - 1; i >= 0; --i )
    {
        if ( action.compare( this.actionList[i] ) >= 0 )
        {
            index = i + 1;
            break;
        }
    }
    this.actionList.splice( index, 0, action );
    return index;
};

waveLib.GadgetState.prototype.findNewActions_ = function()
{
    var actionCount = this.actionList.length;
    var insertIndex = actionCount;
    
    var state = wave.getState();
    var keys = wave.getState().getKeys();
    
    if ( keys.length == 0 && !this.initialized )
    {
        this.initialized = true;
        this.gadget.init();
        return;
    }
    this.initialized = true;
    
    for( var i = 0; i < keys.length; ++i )
    {
        var key = keys[i];
        
        // Acknowledgement for a pending action?
        if ( this.pendingActions[key] )
        {
           delete this.pendingActions[key];
           continue;
        }
        // An old action?
        if ( this.actions[key] )
            continue;
        // It must be a new action
        var action = waveLib.GadgetAction.deserializeAction( key, state.get(key) );
        action.isNew = true;
        // Find out where we need to rollback
        var index = this.insertAction_(action);
        insertIndex = Math.min( insertIndex, index );
        waveLib._clock = Math.max(waveLib._clock, action.clock + 1);
    }
    
    // Do we have to rollback?
    if ( insertIndex < actionCount )
    {
        for( var i = this.actionList.length - 1; i > insertIndex; --i )
        {
            var a = this.actionList[i];
            if ( a.isNew )
                delete a.isNew;
            else
                this.gadget.rollback( a );
        }
    }
    
    // Apply the new actions
    for( var i = insertIndex; i < this.actionList.length; ++i )
    {
        var a = this.actionList[i];
        if ( a.isNew )
            delete a.isNew;
        this.gadget.apply( a );       
    }
    
    this.gadget.polish();
};

////////////////////////////////////////////////////////////
// GadgetAction

/**
* @param key is optional
* @param keyString is optional, but required if key is specified.
*/
waveLib.GadgetAction = function(data, key, keyString)
{
    this.data = data;
    if ( key )
    {
        this.sessionID = key.s;
        this.clock = key.c;
        this.key = keyString;
    }
    else
    {
        this.sessionID = waveLib._session;
        this.clock = waveLib._clock++;
        this.key = JSON.stringify( {s:this.sessionID, c:this.clock} );
    }
};

waveLib.GadgetAction.prototype.getKey = function()
{
    return this.key;
};

waveLib.GadgetAction.prototype.getData = function()
{
    return this.data;
};

waveLib.GadgetAction.prototype.getJSONData = function()
{
    return gadgets.json.stringify( this.data );
};

waveLib.GadgetAction.prototype.compare = function( other )
{
    if ( this.clock < other.clock || ( this.clock == other.clock && this.sessionID < other.sessionID ) )
        return -1;
    if ( this.clock == other.clock && this.sessionID == other.sessionID )
        return 0;
    return 1;        
};

waveLib.GadgetAction.deserializeAction = function( key, data)
{
    var k = gadgets.json.parse(key);
    if ( k && k.s && k.c )    
        return new waveLib.GadgetAction( gadgets.json.parse(data), k, key );
    return null;
};

////////////////////////////////////////////////////////////
// Gadget

waveLib.Gadget = function()
{
    this.state = new waveLib.GadgetState(this);
};

waveLib.Gadget.prototype.onStateChange = function()
{
    this.state.findNewActions_();
};

waveLib.Gadget.prototype.submitAction = function( action )
{
    if ( !this.apply( action ) )
        return;
    this.polish();
    this.state.submitAction_(action);
};

waveLib.Gadget.prototype.init = function()
{
};

waveLib.Gadget.prototype.apply = function( action )
{
};

waveLib.Gadget.prototype.rollback = function( action )
{
};

waveLib.Gadget.prototype.polish = function()
{
};

waveLib.Gadget.prototype.reset = function( action )
{
};

/////////////////////////////////////////////////////////////////////

function MyItem()
{
    this.text = "New task";
    this.status = "0%";
    this.resp = "To be assigned";
    this.start = 1;
    this.end = 1;
    this.total = 1;
    this.level = 0;
    this.isStared = false;
}

function MyGadget()
{
    this.view = null;
    this.items = [];
    this.itemsModified = false;
    this.currentEdit = { item : null, property : null };
    this.currentSelection = [ ];
    this.parent.constructor.call(this);
    this.showTable();
}

MyGadget.extend(waveLib.Gadget);

var counter = 0;

MyGadget.prototype.getItem = function( id )
{
    for( var i = 0; i < this.items.length; ++i )
    {
        var item = this.items[i];
        if ( item.id == id )
            return item;
    }
    return null;
};            

MyGadget.prototype.getItemIndex = function( id )
{
    for( var i = 0; i < this.items.length; ++i )
    {
        var item = this.items[i];
        if ( item.id == id )
            return i;
    }
    return -1;
};            

MyGadget.prototype.apply = function( action )
{
//    $System.Console.WriteLine("Apply: " + action.getKey() );
    
    if ( action.getData().action == "new" )
    {
        var item = action.item;
        if ( !item )
        {
            item = new MyItem();
            item.text = action.getData().text;
            item.id = action.getKey();
            action.item = item;            
//            $System.Console.WriteLine("   new " + item.id );
        }
        action.lastPos = this.items.length;
        this.items.push(item);
        return true;
    }
    else if ( action.getData().action == "del" )
    {
//        $System.Console.WriteLine("   del " + action.getData().id );
        for( var i = 0; i < this.items.length; ++i )
        {
            var item = this.items[i];
            if ( item.id == action.getData().id )
            {
                action.lastPos = i;
                action.item = item;
                this.items.splice( i, 1 );
//                $System.Console.WriteLine("   del " + this.items );
                return true;
            }
        }
    }
    else if ( action.getData().action == "up" )
    {
        for( var i = 1; i < this.items.length; ++i )
        {
            var item = this.items[i];
            if ( item.id == action.getData().id )
            {
                action.lastPos = i;
                action.item = item;
                var tmp = this.items[i-1];
                this.items[i-1] = item;
                this.items[i] = tmp;
                return true;
            }
        }
    }
    else if ( action.getData().action == "down" )
    {
        for( var i = 0; i < this.items.length - 1; ++i )
        {
            var item = this.items[i];
            if ( item.id == action.getData().id )
            {
                action.lastPos = i;
                action.item = item;
                var tmp = this.items[i+1];
                this.items[i+1] = item;
                this.items[i] = tmp;
                return true;
            }
        }
    }
    else if ( action.getData().action == "setStatus" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            action.lastStatus = item.status;
            action.item = item;
            item.status = action.getData().status;
            return true;
        }
    }
    else if ( action.getData().action == "setResp" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            action.lastResp = item.resp;
            action.item = item;
            item.resp = action.getData().resp;
            return true;
        }
    }
    else if ( action.getData().action == "setText" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            action.lastText = item.text;
            action.item = item;
            item.text = action.getData().text;
            return true;
        }
    }
    else if ( action.getData().action == "setStart" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            action.lastStart = item.start;
            action.item = item;
            item.start = action.getData().start;
            return true;
        }
    }
    else if ( action.getData().action == "setEnd" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            action.lastEnd = item.end;
            action.item = item;
            item.end = action.getData().end;
            return true;
        }
    }
    else if ( action.getData().action == "setTotal" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            action.lastTotal = item.total;
            action.item = item;
            item.total = action.getData().total;
            return true;
        }
    }    
    else if ( action.getData().action == "incLevel" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            var index = this.getItemIndex(action.getData().id);
            // The first task in the list cannot be indented
            if ( index == 0 )
                return false;
            // Indentation can only be one larger than at the parent
            var parentItem = this.items[index-1];
            if ( item.level > parentItem.level )
                return false;
            action.lastLevel = item.level;
            action.item = item;
            item.level++;
            return true;
        }
    }    
    else if ( action.getData().action == "decLevel" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            if ( item.level == 0 )
                return false;
            action.lastLevel = item.level;
            action.item = item;
            item.level--;
            return true;
        }
    }    
    return false;
};

MyGadget.prototype.rollback = function( action )
{
//    $System.Console.WriteLine("Rollback: " + action.getKey() );

    if ( action.getData().action == "del" )
    {
        this.items.splice( action.lastPos, 0, action.item );
    }
    else if ( action.getData().action == "new" )
    {
        for( var i = 0; i < this.items.length; ++i )
        {
            if ( this.items[i].id == action.getKey() )
            {
                this.items.splice( i, 1 );
                return;
            }
        }
    }
    else if ( action.getData().action == "down" || action.getData().action == "up" )
    {
        for( var i = 1; i < this.items.length; ++i )
        {
            var item = this.items[i];
            if ( item.id == action.getData().id )
            {
                var tmp = this.items[action.lastPos];
                this.items[action.lastPos] = item;
                this.items[i] = tmp;
                return;
            }
        }
    }
    else if ( action.getData().action == "setStatus" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            item.status = action.lastStatus;
            return;
        }
    }    
    else if ( action.getData().action == "setResp" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            item.resp = action.lastResp;
            return;
        }
    }    
    else if ( action.getData().action == "setText" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            item.text = action.lastText;
            return;
        }
    }    
    else if ( action.getData().action == "setStart" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            item.start = action.lastStart;
            return;
        }
    }    
    else if ( action.getData().action == "setEnd" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            item.end = action.lastEnd;
            return;
        }
    }    
    else if ( action.getData().action == "setTotal" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            item.total = action.lastTotal;
            return;
        }
    }        
    else if ( action.getData().action == "incLevel" || action.getData().action == "decLevel" )
    {
        var item = this.getItem(action.getData().id);
        if ( item )
        {
            item.level = action.lastLevel;
            return;
        }
    }        
};

MyGadget.prototype.polish = function()
{
    if ( this.view == "table" )
    {
        var xml = document.getElementById('tasktable');
        var xml2 = document.getElementById('tasktablebody');
        if ( xml2 )
            xml.removeChild(xml2);
        xml2 = document.createElement('tbody');
        xml2.className = "TaskTableBody";
        xml2.id = "tasktablebody";
        
        var indent = [ 0 ];
        
        for( var i = 0; i < this.items.length; ++i )
        {
            var item = this.items[i];
            var number = "";
            for( var l = 0; l <= item.level; ++l )
            {
                if ( indent.length <= l )
                    indent.push(0);
                if ( l == item.level )
                    indent[l] = indent[l] + 1;
                number += indent[l].toString() + ".";
            }
            var tr = item.tr;
            if ( !tr )
            {
                tr = document.createElement('tr');
                tr.className = "TaskListTR";
                var td1 = document.createElement('td');
                td1.className = "TaskListTD1";
                var input = document.createElement('input');
                input.type = "checkbox";
                input.onclick = waveLib.callback( function() { mygadget.toggleSelection(this); }, item );
                item.inputSelect = input;
                td1.appendChild(input);
                tr.appendChild(td1);
                var td2 = document.createElement('td');
                td2.className = "TaskListTD2";
                var div = document.createElement('div');
                div.className = item.isStared ? "Marked" : "NotMarked";
                div.innerHTML = "&nbsp;";
                item.divStar = div;
                td2.appendChild(div);
                td2.onclick = waveLib.callback( function() { mygadget.toggleStar(this); }, item );
                tr.appendChild(td2);
                var td3 = document.createElement('td');
                td3.className = "TaskListTD";
                var span = document.createElement('span');
                span.appendChild( document.createTextNode( number + " " + item.text ) );
                item.spanText = span;
                td3.appendChild(span);
                td3.onmousedown = waveLib.callback( function() { mygadget.editTaskText( this ); }, item );
                item.tdText = td3;
                tr.appendChild(td3);
                var td4 = document.createElement('td');
                td4.className = "TaskListTD";
                var span = document.createElement('span');
                span.appendChild( document.createTextNode( item.start.toString() ) );
                item.spanStart = span;
                td4.appendChild(span);           
                td4.onmousedown = waveLib.callback( function() { mygadget.editTaskStart(this); }, item );
                item.tdStart = td4;
                tr.appendChild(td4);
                var td5 = document.createElement('td');
                td5.className = "TaskListTD";
                var span = document.createElement('span');
                span.appendChild( document.createTextNode( item.end.toString() ) );
                item.spanEnd = span;
                td5.appendChild(span);           
                td5.onmousedown = waveLib.callback( function() { mygadget.editTaskEnd(this); }, item );
                item.tdEnd = td5;
                tr.appendChild(td5);
                var td6 = document.createElement('td');
                td6.className = "TaskListTD";
                var span = document.createElement('span');
                span.appendChild( document.createTextNode( item.total.toString() ) );
                item.spanTotal = span;
                td6.appendChild(span);           
                td6.onmousedown = waveLib.callback( function() { mygadget.editTaskTotal(this); }, item );
                item.tdTotal = td6;
                tr.appendChild(td6);
                var td7 = document.createElement('td');
                td7.className = "TaskListTD";
                var span = document.createElement('span');
                span.appendChild( document.createTextNode( item.resp ) );
                item.spanResp = span;
                td7.appendChild(span);
                item.tdResp = td7;
                td7.onmousedown = waveLib.callback( function() { mygadget.editTaskResponsibility( this ); }, item );
                tr.appendChild(td7);
                var td8 = document.createElement('td');
                td8.className = "TaskListTD";
                var span = document.createElement('span');
                span.appendChild( document.createTextNode( item.status ) );
                td8.onmousedown = waveLib.callback( function() { mygadget.editTaskStatus( this ); }, item );
                item.spanStatus = span;
                td8.appendChild(span)
                tr.appendChild(td8);
                item.tdStatus = td8;

                item.tr = tr;
            }
            else
            {
                item.spanText.innerHTML = number + " " + item.text;
                item.spanStatus.innerHTML = item.status;
                item.spanResp.innerHTML = item.resp;
                item.spanStart.innerHTML = item.start;
                item.spanEnd.innerHTML = item.end;
                item.spanTotal.innerHTML = item.total;
            }
            if ( i % 2 == 0 )
                tr.style.backgroundColor = "#FFBBBB";
            else
                tr.style.backgroundColor = "#BBFFBB";
            xml2.appendChild(tr);
        }        
        xml.appendChild(xml2);
    }
    else if ( this.view == "charts" )
    {
        var start = "";
        var end = "";
        var data = "chd=t:";
        var labels = "chl=";
        for( var i = 0; i < this.items.length; ++i )
        {
            var item = this.items[i];
            if ( i > 0 )
            {
                data += ",";
                labels += '|';
                start += ",";
                end += ",";
            }
            data += item.total.toString();
            // TODO: Escape text
            labels += item.text;
            start += (item.start-1).toString();
            end += (item.end - item.start + 1).toString();
        }
        var img = document.getElementById('TotalChart');    
        var src='http://chart.apis.google.com/chart?cht=p3&' + data + '&chs=500x200&' + labels;
        img.src = src;

        var img = document.getElementById('GanttChart');    
        var src='http://chart.apis.google.com/chart?cht=bhs&chco=FFFFFF,4D89F9&chd=t:' + start + '|' + end + '&chs=550x' + (20 + 28 * this.items.length).toString() + '&chxt=x&chds=0,24,0,24&chxr=0,1,24,1';
        img.src = src;
    }

    gadgets.window.adjustHeight();
};

MyGadget.prototype.newTask = function()
{
    this.submitAction( new waveLib.GadgetAction( {action:"new", text:"New task"} ) );
};

MyGadget.prototype.deleteTasks = function()
{
    if ( this.view != "table" )
        return;
        
    for( var i = 0; i < this.currentSelection.length; ++i )
    {
        var item = this.getItem( this.currentSelection[i] );
        if ( !item )
            continue;
        this.submitAction( new waveLib.GadgetAction( {action:"del", id:item.id} ) );
    }
    this.currentSelection = [];
};

MyGadget.prototype.editTaskStatus = function(item)
{
    if ( !item.tr || (this.currentEdit.item == item && this.currentEdit.property == "status" ) )
        return;
    
    if ( this.currentEdit.item )
        this.commitEdit_();                   
    this.currentEdit = { item : item, property : "status" };
    
    if ( !item.selectStatus )
    {
        var s = document.createElement("select");
        s.onchange = waveLib.callback( function() { mygadget.commitTaskStatus( this ); }, item );
        for( var i = 0; i <= 100; i += 10 )
        {
            var o = document.createElement("option");
            var str = i.toString() + "%";
            o.appendChild( document.createTextNode( str ) );
            s.appendChild(o);
            if ( str == item.status )
                s.selectedIndex = i;
        }
        item.selectStatus = s;
    }
    item.tdStatus.replaceChild( item.selectStatus, item.spanStatus );
};

MyGadget.prototype.commitTaskStatus = function()
{
    var item = this.currentEdit.item;
    if ( !item )
        return;
    var value = item.selectStatus.options[item.selectStatus.selectedIndex].text;
    if ( item.status != value )
        this.submitAction( new waveLib.GadgetAction( {action:"setStatus", status:value, id:item.id} ) );
    this.stopEdit_();
};

MyGadget.prototype.editTaskResponsibility = function(item)
{
    if ( !item.tr || (this.currentEdit.item == item && this.currentEdit.property == "resp" ) )
        return;
    if ( this.currentEdit.item )
        this.commitEdit_();                    
    this.currentEdit = { item : item, property : "resp" };
    
    if ( !item.inputResp )
    {
        var s = document.createElement("input");
        s.type = "text";
        s.className = "TaskListTextInput";        
        s.onchange = waveLib.callback( function() { mygadget.commitTaskResponsibility( this ); }, item );
        item.inputResp = s;
    }
    item.tdResp.replaceChild( item.inputResp, item.spanResp );
    item.inputResp.value = item.resp;
    item.inputResp.select();
    item.inputResp.focus();
};

MyGadget.prototype.commitTaskResponsibility = function()
{
    var item = this.currentEdit.item;
    if ( !item )
        return;
    var value = item.inputResp.value;
    if ( item.resp != value )
        this.submitAction( new waveLib.GadgetAction( {action:"setResp", resp:value, id:item.id} ) );
    this.stopEdit_();
};

MyGadget.prototype.editTaskText = function(item)
{
    if ( !item.tr || (this.currentEdit.item == item && this.currentEdit.property == "text" ) )
        return;
    
    if ( this.currentEdit.item )
        this.commitEdit_();               
    this.currentEdit = { item : item, property : "text" };
    
    if ( !item.inputText )
    {
        var s = document.createElement("input");
        s.type = "text";
        s.className = "TaskListTextInput";        
        s.onchange = waveLib.callback( function() { mygadget.commitTaskText( this ); }, item );
        item.inputText = s;
    }
    item.tdText.replaceChild( item.inputText, item.spanText );
    item.inputText.value = item.text;
    item.inputText.select();
    item.inputText.focus();
};

MyGadget.prototype.commitTaskText = function()
{
    var item = this.currentEdit.item;
    if ( !item )
        return;
    var value = item.inputText.value;
    if ( item.text != value )
        this.submitAction( new waveLib.GadgetAction( {action:"setText", text:value, id:item.id} ) );
    this.stopEdit_();
};

MyGadget.prototype.editTaskStart = function(item)
{
    if ( !item.tr || (this.currentEdit.item == item && this.currentEdit.property == "start" ) )
        return;
    
    if ( this.currentEdit.item )
        this.commitEdit_();                
    this.currentEdit = { item : item, property : "start" };
    
    if ( !item.inputStart )
    {
        var s = document.createElement("input");
        s.type = "text";
        s.className = "TaskListTextInput";        
        s.onchange = waveLib.callback( function() { mygadget.commitTaskStart( this ); }, item );
        item.inputStart = s;
    }
    item.tdStart.replaceChild( item.inputStart, item.spanStart );
    item.inputStart.value = item.start;
    item.inputStart.select();
    item.inputStart.focus();
};

MyGadget.prototype.commitTaskStart = function()
{
    var item = this.currentEdit.item;
    if ( !item )
        return;
    var value = parseFloat( item.inputStart.value );
    if ( item.start != value && !isNaN(value ) )
        this.submitAction( new waveLib.GadgetAction( {action:"setStart", start:value, id:item.id} ) );
    this.stopEdit_();
};

MyGadget.prototype.editTaskEnd = function(item)
{
    if ( !item.tr || (this.currentEdit.item == item && this.currentEdit.property == "end" ) )
        return;
    
    if ( this.currentEdit.item )
        this.commitEdit_();            
    this.currentEdit = { item : item, property : "end" };
    
    if ( !item.inputEnd )
    {
        var s = document.createElement("input");
        s.type = "text";
        s.className = "TaskListTextInput";        
        s.onchange = waveLib.callback( function() { mygadget.commitTaskEnd( this ); }, item );
        item.inputEnd = s;
    }
    item.tdEnd.replaceChild( item.inputEnd, item.spanEnd );
    item.inputEnd.value = item.end;
    item.inputEnd.select();
    item.inputEnd.focus();
};

MyGadget.prototype.commitTaskEnd = function()
{
    var item = this.currentEdit.item;
    if ( !item )
        return;
    var value = parseFloat( item.inputEnd.value );
    if ( item.end != value && !isNaN(value ) )
        this.submitAction( new waveLib.GadgetAction( {action:"setEnd", end:value, id:item.id} ) );
    this.stopEdit_();
};

MyGadget.prototype.editTaskTotal = function(item)
{
    if ( !item.tr || (this.currentEdit.item == item && this.currentEdit.property == "total" ) )
        return;
    
    if ( this.currentEdit.item )
        this.commitEdit_();            
    this.currentEdit = { item : item, property : "total" };
    
    if ( !item.inputTotal )
    {
        var s = document.createElement("input");
        s.type = "text";
        s.className = "TaskListTextInput";        
        s.onchange = waveLib.callback( function() { mygadget.commitTaskTotal( this ); }, item );
        item.inputTotal = s;
    }
    item.tdTotal.replaceChild( item.inputTotal, item.spanTotal );
    item.inputTotal.value = item.total;
    item.inputTotal.select();
    item.inputTotal.focus();
};

MyGadget.prototype.commitTaskTotal = function()
{
    var item = this.currentEdit.item;
    if ( !item )
        return;
    var value = parseFloat( item.inputTotal.value );
    if ( item.total != value && !isNaN(value ) )
        this.submitAction( new waveLib.GadgetAction( {action:"setTotal", total:value, id:item.id} ) );
    this.stopEdit_();
};

MyGadget.prototype.commitEdit_ = function()
{
    if ( !this.currentEdit.item )
        return;
        
    if ( this.currentEdit.property == "status" )
    {        
        this.commitTaskStatus();
    }
    else if ( this.currentEdit.property == "resp" )
    {
        this.commitTaskResponsibility();
    }
    else if ( this.currentEdit.property == "text" )
    {
        this.commitTaskText();
    }
    else if ( this.currentEdit.property == "start" )
    {
        this.commitTaskStart();
    }
    else if ( this.currentEdit.property == "end" )
    {
        this.commitTaskEnd();
    }
    else if ( this.currentEdit.property == "total" )
    {
        this.commitTaskTotal();
    }
    this.stopEdit_();
};

MyGadget.prototype.stopEdit_ = function()
{
    if ( !this.currentEdit.item )
        return;
        
    if ( this.currentEdit.property == "status" )
    {        
        this.currentEdit.item.tdStatus.replaceChild( this.currentEdit.item.spanStatus, this.currentEdit.item.selectStatus );
    }
    else if ( this.currentEdit.property == "resp" )
    {
        this.currentEdit.item.tdResp.replaceChild( this.currentEdit.item.spanResp, this.currentEdit.item.inputResp );
    }
    else if ( this.currentEdit.property == "text" )
    {
        this.currentEdit.item.tdText.replaceChild( this.currentEdit.item.spanText, this.currentEdit.item.inputText );
    }
    else if ( this.currentEdit.property == "start" )
    {
        this.currentEdit.item.tdStart.replaceChild( this.currentEdit.item.spanStart, this.currentEdit.item.inputStart );
    }
    else if ( this.currentEdit.property == "end" )
    {
        this.currentEdit.item.tdEnd.replaceChild( this.currentEdit.item.spanEnd, this.currentEdit.item.inputEnd );
    }
    else if ( this.currentEdit.property == "total" )
    {
        this.currentEdit.item.tdTotal.replaceChild( this.currentEdit.item.spanTotal, this.currentEdit.item.inputTotal );
    }
    this.currentEdit.item = null;
};

MyGadget.prototype.toggleSelection = function(item)
{    
    for( var i = 0; i < this.currentSelection.length; ++i )
    {
        var id = this.currentSelection[i];
        if ( id == item.id )
        {
            this.currentSelection.splice(i,1);
            return;
        }
    }
    this.currentSelection.push(item.id);
};

MyGadget.prototype.toggleStar = function(item)
{
    item.isStared = !item.isStared;
    
    var stared = [];
    for( var i = 0; i < this.items.length; ++i )
    {
        var item2 = this.items[i];
        if ( item2.isStared )
            stared.push( item2.id );
    }
//    //waveLib.getState().submitValue( "torben" + "/" + "stared", gadgets.json.stringify(stared));
    if ( item.divStar )
    {
        item.divStar.className = item.isStared ? "Marked" : "NotMarked";
    }
};

MyGadget.prototype.selectAll = function()
{    
    this.currentSelection = [ ];
    for( var i = 0; i < this.items.length; ++i )
    {
        var item = this.items[i];
        if ( item )
        {
            this.currentSelection.push(item.id);
            if ( item.inputSelect )
                item.inputSelect.checked = true;
        }
    }
};

MyGadget.prototype.selectNone = function()
{    
    for( var i = 0; i < this.currentSelection.length; ++i )
    {
        var id = this.currentSelection[i];
        var item = this.getItem(id);
        if ( item && item.inputSelect )
            item.inputSelect.checked = false;
    }
    this.currentSelection = [ ];
};

MyGadget.prototype.selectInvert = function()
{    
    var map = { };
    for( var i = 0; i < this.currentSelection.length; ++i )    
        map[ this.currentSelection[i] ] = true;
        
    this.currentSelection = [ ];
    for( var i = 0; i < this.items.length; ++i )
    {
        var item = this.items[i];
        if ( item && !map[item.id] )
        {
            this.currentSelection.push(item.id);
            if ( item.inputSelect )
                item.inputSelect.checked = true;
        }
        else if ( item )
        {
            if ( item.inputSelect )
                item.inputSelect.checked = false;
        }
    }
};

MyGadget.prototype.selectStared = function()
{    
    this.currentSelection = [ ];
    for( var i = 0; i < this.items.length; ++i )
    {
        var item = this.items[i];
        if ( item )
        {
            if ( item.isStared )
            {
                this.currentSelection.push(item.id);
                if ( item.inputSelect )
                    item.inputSelect.checked = true;
            }
            else
            {
                if ( item.inputSelect )
                    item.inputSelect.checked = false;
            }
        }
    }
};

MyGadget.prototype.moveTasksUp = function()
{
    for( var i = 0; i < this.currentSelection.length; ++i )
    {
        var item = this.getItem( this.currentSelection[i] );
        if ( !item )
            continue;
        this.submitAction( new waveLib.GadgetAction( {action:"up", id:item.id} ) );
    }
};

MyGadget.prototype.moveTasksDown = function()
{
    for( var i = 0; i < this.currentSelection.length; ++i )
    {
        var item = this.getItem( this.currentSelection[i] );
        if ( !item )
            continue;
        this.submitAction( new waveLib.GadgetAction( {action:"down", id:item.id} ) );
    }
};

MyGadget.prototype.incTaskLevel = function()
{
    for( var i = 0; i < this.currentSelection.length; ++i )
    {
        var item = this.getItem( this.currentSelection[i] );
        if ( !item )
            continue;
        this.submitAction( new waveLib.GadgetAction( {action:"incLevel", id:item.id} ) );
    }
};

MyGadget.prototype.decTaskLevel = function()
{
    for( var i = 0; i < this.currentSelection.length; ++i )
    {
        var item = this.getItem( this.currentSelection[i] );
        if ( !item )
            continue;
        this.submitAction( new waveLib.GadgetAction( {action:"decLevel", id:item.id} ) );
    }
};

MyGadget.prototype.showTable = function()
{
    if ( this.view == "table" )
        return;
    
    this.view = "table";    
    
    var box = document.getElementById("Box");
    var boxcontent = document.getElementById("BoxContent");
    if ( boxcontent )
        box.removeChild(boxcontent);
    boxcontent = document.createElement("div");
    boxcontent.style.padding = "24px";
    boxcontent.id = "BoxContent";
    
    var html = '<table style="empty-cells: show; border-collapse: collapse; text-align: left;" id="tasktable">';
    html += '<thead style="font-size: small; font-family: Arial, Sans-Serif">';
    html += '<tr>';
    html += '<th style="border: solid 0px #ffffff">';
    html += '</th>'
    html += '<th style="border: solid 0px #ffffff">Complete';
    html += '</th>';
    html += '<th style="border: solid 1px #888888;">';
    html += 'Name';
    html += '</th>';
   // html += '<th style="border: solid 1px #888888; padding-right: 10px">';
   // html += 'Start<br />';
   // html += 'month';
   // html += '</th>';
   // html += '<th style="border: solid 1px #888888; padding-right: 10px">End<br />month</th>';
   // html += '<th style="border: solid 1px #888888; padding-right: 10px">Total man<br />months</th>';
    html += '<th style="border: solid 1px #888888;">Responsible</th>';
    html += '<th style="border: solid 1px #888888;">Status</th></tr></thead></table>';    
    boxcontent.innerHTML = html;
    box.appendChild(boxcontent);
    
    this.polish();
};

MyGadget.prototype.showCharts = function()
{
    if ( this.view == "charts" )
        return;
        
    this.view = "charts";    
    
    var box = document.getElementById("Box");
    var boxcontent = document.getElementById("BoxContent");
    if ( boxcontent )
        box.removeChild(boxcontent);
    boxcontent = document.createElement("div");
    boxcontent.style.padding = "24px";
    boxcontent.id = "BoxContent";
        
    // var html = '<img src="http://chart.apis.google.com/chart?cht=p3&chd=t:20,20,30,40&chs=500x200&chl=Januar|February|March|April" />';    
    var html = '<h3>Gantt diagram</h3><img id="GanttChart" onload="gadgets.window.adjustHeight();" /><h3 style="padding-top:16px">Total man months allocated for each task</h3><img id="TotalChart" onload="gadgets.window.adjustHeight();"/>';
    boxcontent.innerHTML = html;
    box.appendChild(boxcontent);
    
    this.polish();
};

MyGadget.prototype.init = function()
{
    this.newTask();
};

/////////////////////////////////////////////////////////////////////

function myinit()
{
    mygadget = new MyGadget();
    if (wave && wave.isInWaveContainer()) { wave.setStateCallback(mygadget.onStateChange, mygadget ); }
}

gadgets.util.registerOnLoadHandler(myinit);